package com.spzx.cart.service.imp;

import com.spzx.cart.domain.CartInfo;
import com.spzx.cart.service.CartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.vo.ProductSkuVo;
import com.spzx.product.api.vo.SkuPriceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RemoteProductService remoteProductService;

    /**
     * 获取用户购物车key
     *
     * @param userId
     * @return
     */
    private String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }

    /**
     * 添加商品到购物车
     *
     * @param skuId
     * @param skuNum
     */
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 实现添加商品到购物车的逻辑
        // 获取当前登录用户id SecurityUtils : 权限工具类
        Long userId = SecurityUtils.getUserId();

        // 1. 构建用户购物车key user:cart:userId
        String cartKey = getCartKey(userId);

        // 2. 创建Hash结构绑定操作对象(方便对hash结构进行操作)
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        // 3. 判断用户购物车中是否有该商品 如果包含 直接修改数量 并设置数量上限，如果不包含 直接添加
        String hashKey = skuId.toString();
        int threshold = 5;// 设置数量上限
//        if (hashOps.hasKey(hashKey)) {
        // 判断hash结构中是否有该key 即购物车中是否包含该商品
        if (Boolean.TRUE.equals(hashOps.hasKey(hashKey))) {
            // 有，直接修改数量
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;// 总数
//            cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
            cartInfo.setSkuNum(Math.min(totalCount, threshold));
            hashOps.put(hashKey, cartInfo);// 重新设置
        } else {
            // 没有，判断商品不同的sku 总数不能超过10个
            Long count = hashOps.size();
            if (++count > 10) {
                throw new ServiceException("购物车商品总数不能超过10个!");
            }
            // 有就直接添加 在redis中添加商品
            CartInfo cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuNum(skuNum);
            // 远程调用商品服务 获取商品详情
            //校验商品是否存在 远程调用商品服务 获取商品详情
            R<ProductSkuVo> productSkuVoResult = remoteProductService.getProductVoSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuVoResult.getCode()) {
                throw new ServiceException(productSkuVoResult.getMsg());
            }
            ProductSkuVo productSkuVo = productSkuVoResult.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSkuVo.getSkuName());
            cartInfo.setThumbImg(productSkuVo.getThumbImg());
            cartInfo.setSkuPrice(productSkuVo.getSalePrice());
            cartInfo.setCreateTime(new Date());

            // 添加到购物车中 存到redis中
            hashOps.put(hashKey, cartInfo);

        }
    }

    /**
     * 获取购物车列表
     *
     * @return
     */
    @Override
    public List<CartInfo> getCartList() {

        //获取购物车key
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOps.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList = cartInfoList
                    .stream()
                    .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
                    .collect(Collectors.toList());
        }

        return cartInfoList;
    }

    /**
     * 删除购物车商品
     *
     * @param skuId
     */
    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        hashOps.delete(skuId.toString());
    }

    /**
     * 清空购物车
     */
    @Override
    public void clearCart() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    /**
     * 获取勾选状态的购物车列表
     *
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList() {
        Long userId = SecurityUtils.getUserId();
        String cartKey = this.getCartKey(userId);
        HashOperations<String, String, CartInfo> hashOps = redisTemplate.opsForHash();//没有绑定key,可以直接操作key-value结构


        List<CartInfo> cartCachInfoList = hashOps.values(cartKey);
        List<CartInfo> cartInfoList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            cartInfoList = cartCachInfoList.stream()
                    .filter(cartInfo -> cartInfo.getIsChecked() == 1)// 只筛选出勾选状态的
                    .collect(Collectors.toList());// 收集到集合中
        }
        return cartInfoList;
    }

    /**
     * 更新购物车价格
     *
     * @param userId
     * @return
     */
    @Override
    public Boolean updateCartPrice(Long userId) {

        String cartKey = this.getCartKey(userId);
        HashOperations<String, String, CartInfo> hashOps = redisTemplate.opsForHash();
        List<CartInfo> cartCachInfoList = hashOps.values(cartKey);
        if (CollectionUtils.isEmpty(cartCachInfoList)) {
            for (CartInfo cartInfo : cartCachInfoList) {
                R<SkuPriceVo> skuPriceResult = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER);
                if (R.FAIL == skuPriceResult.getCode()) {
                    throw new ServiceException(skuPriceResult.getMsg());
                }
                //实时价格
                cartInfo.setSkuPrice(skuPriceResult.getData().getSalePrice());
//                cartInfo.setCartPrice(skuPriceResult.getData().getSalePrice());
                hashOps.put(cartKey, cartInfo.getSkuId().toString(), cartInfo);
            }
        }
        return true;
    }

    /**
     * 删除勾选状态的购物车列表
     *
     * @param userId
     * @return
     */
    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = this.getCartKey(userId);
        HashOperations<String, String, CartInfo> hashOps = redisTemplate.opsForHash();
        List<CartInfo> cartCachInfoList = hashOps.values(cartKey);
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            cartCachInfoList.stream()
                    .filter(cartInfo -> cartInfo.getIsChecked() == 1)
                    .forEach(cartInfo -> hashOps.delete(cartKey, cartInfo.getSkuId().toString()));
        }
/*        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            for (CartInfo cartInfo : cartCachInfoList) {
                // 只删除勾选状态的
                if (cartInfo.getIsChecked() == 1) {
                    hashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }*/
        return true;
    }

    /**
     * 勾选购物车商品
     *
     * @param skuId
     * @param isChecked
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        if (hashOps.hasKey(skuId.toString())) {
            CartInfo cartInfo = hashOps.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            hashOps.put(skuId.toString(), cartInfo);
        }

    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityUtils.getUserId();
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOps.values();
        cartCachInfoList.forEach(cartInfo -> {
            CartInfo cartInfoUpdate = hashOps.get(cartInfo.getSkuId().toString());
            cartInfoUpdate.setIsChecked(isChecked);

            hashOps.put(cartInfo.getSkuId().toString(), cartInfoUpdate);
        });
    }


}
